﻿ #region Disclaimer/Info
 
 /////////////////////////////////////////////////////////////////////////////////////////////////
 //
 //   File:		ConfigurationService.cs
 //   Website:		http://dexterblogengine.com/
 //   Authors:		http://dexterblogengine.com/About.ashx
 //   Rev:		1
 //   Created:		19/01/2011
 //   Last edit:		19/01/2011
 //   License:		GNU Library General Public License (LGPL)
 // 
 //   For updated news and information please visit http://dexterblogengine.com/
 //   Dexter is hosted to Codeplex at http://dexterblogengine.codeplex.com
 //   For any question contact info@dexterblogengine.com
 //
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 #endregion

using System;
using System.Threading;
using Dexter.Caching;
using Dexter.Domain.Model;
using Dexter.Logger.Contracts;
using Dexter.Repository;
using Topics.Radical.Validation;

namespace Dexter.Services.Implementation {
	/// <summary>
	/// 	Implementation of <see cref = "IConfigurationService" />.
	/// </summary>
	public class ConfigurationService : IConfigurationService {
		const string CACHE_KEY = "Dexter.Site.Configuraton";

		/// <summary>
		/// 	The lock object use to manage multi access to the configuration.
		/// </summary>
		protected static readonly ReaderWriterLockSlim @Lock = new ReaderWriterLockSlim ( );

		/// <summary>
		/// 	An instance of a concrete implementation of <see cref = "IConfigurationRepository" />
		/// </summary>
		protected readonly IConfigurationRepository ConfigurationRepository;

		/// <summary>
		/// 
		/// </summary>
		protected readonly ISetupService SetupService;

		/// <summary>
		/// 	The logger.
		/// </summary>
		protected readonly ILogger Logger;

		readonly ICacheProvider cacheService;

		/// <summary>
		/// 	Initializes a new instance of the <see cref = "ConfigurationService" /> class.
		/// </summary>
		/// <param name = "cacheService">The cache service.</param>
		/// <param name = "configurationRepository">The configuration repository.</param>
		/// <param name = "logger">The logger.</param>
		public ConfigurationService ( ICacheProvider cacheService, IConfigurationRepository configurationRepository, ILogger logger , ISetupService setupService ) {
			this.cacheService = cacheService;
			this.ConfigurationRepository = configurationRepository;
			this.Logger = logger;
			SetupService = setupService;
		}

		/// <summary>
		/// 	Return the configuration of Dexter
		/// </summary>
		/// <value>The configuration.</value>
		public virtual SiteConfiguration Configuration {
			get {
				if(!SetupService.IsInstalled)
					return SiteConfiguration.GetDefaultConfiguration ( );

				var result = cacheService.Get <SiteConfiguration> ( CACHE_KEY );

				if ( result != null ) {
					return result;
				}

				var model = ConfigurationRepository.GetConfiguration ( );

				if ( model != null ) {
					result = model.SerializedConfiguration.Deserialize <SiteConfiguration> ( );
				}
				else {
					Logger.Warn ( "Configuration Safe Mode" );
					result = SiteConfiguration.GetDefaultConfiguration ( );
				}

				cacheService.Put ( CACHE_KEY , result , TimeSpan.FromDays ( 7 ) );

				return result;
			}
		}

		/// <summary>
		/// 	Saves the configuration.
		/// </summary>
		/// <param name = "configuration">The configuration.</param>
		/// <exception cref = "ArgumentNullException"> If <paramref name = "configuration" /> is <c>null</c>.</exception>
		public virtual void SaveConfiguration ( SiteConfiguration configuration ) {
			Ensure.That ( configuration )
				.Named ( "configuration" )
				.WithPreview ( ( v , e ) => Logger.Warn ( v.GetFullErrorMessage ( ) , e ) )
				.IsNotNull ( )
				.WithMessage ( "Invalid configuration." );

			var conf = ConfigurationRepository.GetConfiguration ( ) ?? new Domain.Model.Configuration ( );

			conf.SerializedConfiguration = configuration.Serialize ( );

			ConfigurationRepository.SaveConfiguration ( conf );

			cacheService.Put ( CACHE_KEY, configuration, TimeSpan.FromDays ( 7 ) );
		}
	}
}
